package view;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Observable;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.Timer;

import listeners.BuyListener;
import listeners.ChatListener;
import listeners.LoginListener;
import model.ModelShop;
import model.Order;
import model.Product;
import model.ProductList;
import netzwerk.TimeReceiverThread;
import verifiers.LoginVerifier;
import example.OrderRenderer;

public class ViewCustomer extends JFrame implements java.util.Observer {

	private static final long serialVersionUID = -8397051218414537000L;

	private Container contentPane;
	private JScrollPane scrollPaneHist;
	private JScrollPane scrollPaneProdL;
	public JList<Order> orderList;
	private Container inputContainer;
	private JTable productTable;
	private JButton buttonBuy;
	private JButton buttonChat;
	private JLabel timeLabel;
	private JFrame loginFrame;
	private JButton loginButton;
	private JTextField userText;
	private JPasswordField passwordText;

	private ProductList productList;

	private Product[] products;
	private Object[][] productTableContent;

	DatagramSocket dSocket;
	AtomicBoolean timeThreadActive;

	private LoginVerifier loginVerifier;

	private boolean nameVorhanden;

	public ViewCustomer() {

		super("ViewCustomer Gruppe 11");
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		contentPane = this.getContentPane();
		contentPane.setLayout(new BorderLayout());

		// Historie
		orderList = new JList<>();
		orderList.setCellRenderer(new OrderRenderer());
		scrollPaneHist = new JScrollPane(orderList);

		// Produktliste und Input
		inputContainer = new Container();
		inputContainer.setLayout(new BoxLayout(inputContainer, BoxLayout.Y_AXIS));

		productTable = new JTable();

		scrollPaneProdL = new JScrollPane(productTable);
		inputContainer.add(scrollPaneProdL);

		buttonBuy = new JButton("buy");
		inputContainer.add(buttonBuy);

		buttonChat = new JButton("Open chat");
		inputContainer.add(getButtonChat());

		timeLabel = new JLabel();
		inputContainer.add(timeLabel);

		contentPane.add(scrollPaneHist, BorderLayout.WEST);
		contentPane.add(inputContainer, BorderLayout.CENTER);

		this.pack();
		this.setVisible(true);

	}

	//Timer per Datagram
	public void startTimer() {

		try {

			final DatagramSocket dSocket = new DatagramSocket();

			// Neuer Thread zum Empfangen des Time-Packets (so wird verhindert, dass der Thread
			// nach dem Senden für immer auf eine Antwort wartet, falls das Paket verloren
			// gegangen ist)
			(new TimeReceiverThread(this, dSocket, timeThreadActive)).start();

			// Jede Sekunde Time-Anfrage senden
			final Timer t = new Timer(1000, new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent event) {

					// Server-Adresse angeben
					InetAddress internetAddr = null;
					try {
						internetAddr = InetAddress.getByName("localhost");
					} catch (UnknownHostException e2) {
						System.out.println("Host nicht bekannt.");
						e2.printStackTrace();
					}

					// Nachricht erzeugen und ins richtige Format bringen
					String command = "time"; // "time" soll an Server gesendet werden

					byte buffer[] = null;
					buffer = command.getBytes();

					// Paket vorbereiten - Ziel: localhost - Port: 6667
					DatagramPacket packet = new DatagramPacket(buffer, buffer.length, internetAddr,
							6667);

					// Paket versenden
					try {
						dSocket.send(packet);
					} catch (IOException e) {
						// Bei Fehlern beim Senden/Empfangen der Zeit, wird der Socket
						// geschlossen und die Uhrzeit wird nicht mehr aktualisiert
						// Die Anwendung kann trotzdem weiterhin genutzt werden
						System.out
								.println("Time-Request failed. Closing connection. Stop sending time-requests.");
						if (!dSocket.isClosed()) {
							dSocket.close();
						}
						((Timer) event.getSource()).stop();
					}
				}
			});

			t.start(); // Timer für das Anfrageintervall starten

		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("Socket konnte nicht erstellt werden");
		}
		// Hier kann Socket nicht geschlossen werden, da er weiterhin benötigt wird.

	}

	
	@Override
	public void update(Observable o, Object arg) {
		productList = ((ModelShop) o).getProductList();
		this.pack();

	}

	//Listener	
	public void addBuyListener(final BuyListener buyListener) {
		buttonBuy.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				loginButton = new JButton("login");
				if (buyListener.buy()) {
					productTable.clearSelection();
					openLoginDialog();
				}

			}

		});

	}

	
	public void addChatListener(final ChatListener chatListener) {
		setNameVorhanden(false);
		getButtonChat().addActionListener(new ActionListener() {
			private String username;

			@Override
			public void actionPerformed(ActionEvent e) {
				System.out.println("openChat");
				if (nameVorhanden) {
					username = (String) JOptionPane
							.showInputDialog(
									null,
									"Der Name ist bereits vorhanden.\n Bitte geben Sie einen anderen Namen ein.",
									"Chat öffnen", JOptionPane.INFORMATION_MESSAGE, null, null, "");
				} else {

					username = (String) JOptionPane.showInputDialog(null,
							"Bitte geben Sie Ihren Namen ein.", "Chat öffnen",
							JOptionPane.INFORMATION_MESSAGE, null, null, "");
				}

				if (username.equals(null) || username.trim().equals("")) {
					System.out.println("Bitte Namen eingeben.");
				} else {
					nameVorhanden = false;
					chatListener.openChat(username);
				}
			}

		});

	}

	
	public void addLoginListener(final LoginListener loginListener) {
		loginButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				if (loginVerifier.verify(userText) && loginVerifier.verify(passwordText)) {
					loginListener.login(userText.getText(), new String(passwordText.getPassword()));
					loginFrame.dispose();
					loginFrame = null;
				}
			}

		});
	}


	//Login-Dialog
	private void openLoginDialog() {

		// Dialogframe erzeugen
		loginFrame = new JFrame("Login");
		loginFrame.setSize(300, 190);
		loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		JPanel panel = new JPanel();
		loginFrame.add(panel);

		// Inhalte des Dialogs erstellen
		panel.setLayout(null);

		JLabel instructionLabel = new JLabel("Bitte geben Sie Ihre Login-Daten ein!");
		instructionLabel.setBounds(10, 10, 280, 25);
		panel.add(instructionLabel);

		loginVerifier = new LoginVerifier();

		JLabel userLabel = new JLabel("User");
		userLabel.setBounds(10, 40, 80, 25);
		panel.add(userLabel);

		userText = new JTextField(20);
		userText.setBounds(100, 40, 160, 25);
		userText.setInputVerifier(loginVerifier);
		// userText.setText("admin");// Nur zum Testen; wieder rausnehmen!!
		panel.add(userText);

		JLabel passwordLabel = new JLabel("Password");
		passwordLabel.setBounds(10, 70, 80, 25);
		panel.add(passwordLabel);

		passwordText = new JPasswordField(20);
		passwordText.setBounds(100, 70, 160, 25);
		passwordText.setInputVerifier(loginVerifier);
		// passwordText.setText("admin"); // Nur zum Testen; wieder rausnehmen!!
		panel.add(passwordText);

		loginButton.setBounds(10, 110, 80, 25);
		loginFrame.getRootPane().setDefaultButton(loginButton); // Loginbutton mit Enter auslösen
		panel.add(loginButton);

		loginFrame.setVisible(true);
	}
	

	//Getter und Setter
	public JTable getProductTable() {
		return productTable;
	}
	
	public Object[][] getProductTableContent() {

		products = new Product[0];
		products = (Product[]) productList.toArray();
		productTableContent = new Object[products.length][4];
		int i = 0;
		for (Product product : products) {
			System.out.println(product.getName());
			productTableContent[i][0] = product.getName();
			productTableContent[i][1] = product.getPrice();
			productTableContent[i][2] = product.getQuantity();
			productTableContent[i][3] = 0;
			System.out.println("name: " + productTableContent[i][0] + " price: "
					+ productTableContent[i][1] + " maxCount: " + productTableContent[i][2]);
			i++;
		}
		return productTableContent;
	}

	public void setDSocket(DatagramSocket dSocket) {
		this.dSocket = dSocket;
	}

	public JLabel getTimeLabel() {
		return timeLabel;
	}

	public void setTimeThreadActive(AtomicBoolean timeThreadActive) {
		this.timeThreadActive = timeThreadActive;
	}

	public void setNameVorhanden(boolean nameVorhanden) {
		this.nameVorhanden = nameVorhanden;
	}

	public JButton getButtonChat() {
		return buttonChat;
	}

}
